package cn.initcap.algorithm.lambda;

import java.time.Year;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;

/**
 * Stream操作示例
 *
 * @author initcap
 * @date Created in 2018/7/29 PM8:26.
 */
public class StreamTest {

    public static void main(String[] args) {
        Book nails = Book.builder().id(1).title("Fundamentals of Chinese Fingernail Image")
                .name(Arrays.asList("Li", "Fu", "Initcap")).pageCount(new int[]{256})
                .year(Year.of(2014)).height(25.2).topic(Topic.MEDICINE).build();
        Book dragon = Book.builder().id(2).title("Compilers: Principles,Techniques and Tools")
                .name(Arrays.asList("Aho", "Lam", "Sethi", "Ullman")).pageCount(new int[]{1009})
                .year(Year.of(2006)).height(23.6).topic(Topic.COMPUTING).build();
        Book voos = Book.builder().id(3).title("Lord of the Rings").name(Arrays.asList("Tolkien", "Initcap"))
                .pageCount(new int[]{531, 416, 624}).year(Year.of(1995)).height(23.0).topic(Topic.FICTION).build();
        List<Book> library = new ArrayList<>();
        library.add(nails);
        library.add(dragon);
        library.add(voos);

        //只包含计算过的图书的流
        Stream<Book> computingBooks = library.stream().filter(b -> b.getTopic() == Topic.COMPUTING);
        computingBooks.forEach(System.out::println);
        System.out.println("==========computingBooks end ===============");
        //图书标题的流
        Stream<String> bookTitles = library.stream().map(Book::getTitle);
        bookTitles.forEach(System.out::println);
        System.out.println("============ bookTitles end ================");
        //Book的流，根据标题排序
        Stream<Book> booksSortedByTitle = library.stream().sorted(Comparator.comparing(Book::getTitle));
        booksSortedByTitle.forEach(System.out::println);
        System.out.println("======== booksSortedByTitle end ===========");
        //使用这个排序流创建一个作者流，根据图书标题排序，并且去除重复的
        Stream<String> nameInBookTitleOrder = library.stream().sorted(Comparator.comparing(Book::getTitle)).flatMap(book -> book.getName().stream()).distinct();
        nameInBookTitleOrder.forEach(System.out::println);
        System.out.println("====== nameInBookTitleOrder end =========");
        //以标题的字母顺序生成前100个图书的流
        Stream<Book> readingList = library.stream().sorted(Comparator.comparing(Book::getTitle)).limit(100);
        readingList.forEach(System.out::println);
        System.out.println("=========== readingList end ===========");
        //除去前100个图书的流
        Stream<Book> remainderList = library.stream().sorted(Comparator.comparing(Book::getTitle)).skip(100);
        remainderList.forEach(System.out::println);
        System.out.println("=========== remainderList end =============");
        //图书馆中最早出版的书
        Optional<Book> oldest = library.stream().min(Comparator.comparing(Book::getYear));
        System.out.println(oldest.get());
        System.out.println("============== oldest end =================");
        //图书馆中图书的标题集合
        Set<String> titles = library.stream().map(Book::getTitle).collect(Collectors.toSet());
        titles.forEach(System.out::println);
        System.out.println("=============== titles end =================");
        //获得所有图书所有卷的所有页数
        int totalPageCount = library.stream().flatMapToInt(b -> IntStream.of(b.getPageCount())).sum();
        System.out.println("所有图书所有卷的所有页数 : " + totalPageCount);
        List<Book> multipleNameHistories = library.stream().filter(b -> b.getTopic() == Topic.FICTION)
                .peek(b -> System.out.println(b.getTitle())).filter(b -> b.getName().size() > 1).collect(Collectors.toList());

        Stream<Book> booksSortedByNameCount = library.stream().sorted(Comparator.comparing(Book::getName, Comparator.comparing(List::size)));
        booksSortedByNameCount.forEach(System.out::println);
        System.out.println("============= booksSortedByNameCount end =========");

    }

    @Getter
    enum Topic {
        HISTORY(1, "历史"),
        PROGRAMMING(2, "编程"),
        MEDICINE(3, "医学"),
        FICTION(4, "小说"),
        COMPUTING(5, "计算过的");
        private int code;
        private String name;

        Topic(int code, String name) {
            this.code = code;
            this.name = name;
        }
    }

    @Data
    @Builder
    static class Book {
        private Integer id;
        private String title;
        private Year year;
        private List<String> name;
        private int[] pageCount;
        private Topic topic;
        private double height;

    }

}
